package lambda;

import org.junit.Test;

import java.util.Comparator;
import java.util.HashMap;
import java.util.function.Consumer;

/**
 * (lambda形参列表) -> (lambda体)
 * 对应着重写的接口中的抽象方法的形参列表 -> 对应着接口的实现类要重写的方法的方法体。
 *
 * Lambda表达式的本质：
 * > 一方面，lambda表达式作为接口的实现类的对象。---> 万事万物皆对象
 * > 另一方面，lambda表达式是一个匿名函数。
 *
 * 函数式接口
 * 1.什么是函数式接口？
 * > 如果接口中只声明有一个抽象方法，则此接口就称为函数式接口。
 * > 因为只有给函数式接口提供实现类的对象时，我们才可以使用lambda表达式。
 * 2.API中函数式接口所在的包
 * > 声明的函数式接口都在java.util.function包下。
 *
 */
public class LambdaTest {
    // 语法格式一： 无参，无返回值
    @Test
    public void test1() {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                System.out.println("我爱北京天安门。");
            }
        };

        Runnable runnable = () -> System.out.println("我爱北京天安门。");
        new Thread(runnable).start();

        new Thread(() -> {
            System.out.println("kdhciuwk");
            System.out.println();
        }).start();


        new Thread(() -> System.out.println()).start();
        new Thread(System.out::println).start();
    }

    // 语法格式二：Lambda需要一个参数，但是没有返回值
    @Test
    public void test2() {
        Consumer<String> consumer = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        consumer.accept("谎言和誓言的区别是什么？");

        Consumer<String> consumer1 = (String s) -> System.out.println(s + "\t");
        consumer1.accept("一个是听的人当真了，一个是说的人当真了。");
    }

    // 语法格式三：数据类型可以省略，因为可由编译器推断得出，称为“类型推断”
    @Test
    public void test3() {// 类型推断

        Consumer<String> consumer1 = (s) -> System.out.println(s + "\t");
        consumer1.accept("一个是听的人当真了，一个是说的人当真了。");

        HashMap<String, Integer> map = new HashMap<>();
        var entrySet = map.entrySet();

    }

    // 语法格式四：Lambda 若只需要一个参数时，参数的小括号可以省略
    @Test
    public void test4() {
        Consumer<String> consumer1 = s -> System.out.println(s + "\t");
        consumer1.accept("一个是听的人当真了，一个是说的人当真了。");
    }

    // 语法格式五：Lambda 需要两个或以上的参数，多条执行语句，并且可以有返回值
    @Test
    public void test5() {
        Comparator<Integer> comparator = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                System.out.println(o1);
                System.out.println(o2);
                return o1.compareTo(o2);
            }
        };
        System.out.println(comparator.compare(12, 21));

        Comparator<Integer> comparator1 = (o1, o2) -> {
            System.out.println(o1);
            System.out.println(o2);
            return o1.compareTo(o2);
        };
        System.out.println(comparator1.compare(12, 1));

    }

    // 语法格式六： 当Lambda体只有一条语句时， return与大括号如若有，都可以省略。
    @Test
    public void test6() {
        Comparator<Integer> comparator = (o1, o2) -> {
            return o1.compareTo(o2);
        };

        Comparator<Integer> comparator2 = (o1, o2) -> o1.compareTo(o2);
        Comparator<Integer> comparator3 = Integer::compareTo;

        System.out.println(comparator2.compare(11, 12));

    }

}